// $Id: cons.cpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#include <typeinfo>
#include <boost/test/unit_test.hpp>
#include <xpcom/ptr.hpp>
#include <xpcom/result_code.hpp>
#include <xpcom/string.hpp>
#include "interface_def.hpp"

BOOST_AUTO_TEST_CASE(test_cons)
{
    using namespace xpcom;

    ref_ptr<IBase> p(X_make_instance());
    BOOST_CHECK_EQUAL(X_count(), 1);

    BOOST_CHECK(p);
    BOOST_CHECK_EQUAL(p->ref(), 1);

    ref_ptr<IA> p1(dynamic_pointer_cast<IA>(p));
    BOOST_CHECK(p1);
    BOOST_CHECK_EQUAL(p1->ref(), 2);

    ref_ptr<IB> p2 = dynamic_pointer_cast<IB>(p1);
    BOOST_CHECK(p2);
    BOOST_CHECK_EQUAL(p2->ref(), 3);

    {
        ref_ptr<IB> pp2 = p2;
        BOOST_CHECK(pp2);
        BOOST_CHECK_EQUAL(pp2, p2);
        BOOST_CHECK_EQUAL(pp2->ref(), 4);
    }

    ref_ptr<IC> p3;
    p3 = polymorphic_pointer_cast<IC>(p1);
    BOOST_CHECK(p3);
    BOOST_CHECK_EQUAL(p3->ref(), 4);

    ref_ptr<IB> p4 = polymorphic_pointer_cast<IC>(p1);
    BOOST_CHECK(p4);
    BOOST_CHECK_EQUAL(p4->ref(), 5);

    try {
        ref_ptr<ID> ppp = polymorphic_pointer_cast<ID>(p1);
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK_EQUAL(e.code(), NS_ERROR_NO_INTERFACE);
    } catch (const std::bad_cast&) {
        BOOST_CHECK(true);
    }

    p2 = p3;

    ref_ptr<ID> p5 = dynamic_pointer_cast<ID>(p1);
    BOOST_CHECK(!p5);
    BOOST_CHECK_EQUAL(p->ref(), 5);

    noref_ptr<IC> p6 = p3;
    BOOST_CHECK(p6);
    BOOST_CHECK_EQUAL(p6->ref(), 5);

    {
        noref_ptr<IC> p7;
        p7 = p3;
        BOOST_CHECK(p7);
        BOOST_CHECK_EQUAL(p7->ref(), 5);
    }

    ref_ptr<IC> p8 = p6;
    BOOST_CHECK(p8 == p6);
    BOOST_CHECK_EQUAL(p8->ref(), 6);

    ref_ptr<IC> p9;
    p9 = p6;
    BOOST_CHECK(p9);
    BOOST_CHECK_EQUAL(p9->ref(), 7);

    swap(p8, p9);

    ref_ptr<IB> p10(p6);
    BOOST_CHECK(p10);
    BOOST_CHECK_EQUAL(p10->ref(), 8);

    ref_ptr<IA> p11;
    p11 = dynamic_pointer_cast<IA>(p6);
    BOOST_CHECK(p11);
    BOOST_CHECK_EQUAL(p11->ref(), 9);

    ref_ptr<ID> p12;
    p12 = dynamic_pointer_cast<ID>(p6);
    BOOST_CHECK(!p12);

    ref_ptr<IA> p13(p11.get(), false);
    BOOST_CHECK(p13);
    BOOST_CHECK_EQUAL(p13->ref(), 9);
    p13.release();

    ref_ptr<IB> p14(get_pointer(p6));
    BOOST_CHECK_EQUAL(p->ref(), 10);

    noref_ptr<IB> p15 = get_pointer(p14);
    BOOST_CHECK_EQUAL(p->ref(), 10);

    ref_ptr<IA> p16 = dynamic_pointer_cast<IA>(p15);
    BOOST_CHECK(p16);
    BOOST_CHECK_EQUAL(p->ref(), 11);

    BOOST_CHECK(p1.equal(p15));

    BOOST_CHECK_EQUAL(X_count(), 1);
}
